package ru.bragnikita.util.chsconv;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.AndFileFilter;
import org.apache.commons.io.filefilter.NameFileFilter;
import org.apache.commons.io.filefilter.NotFileFilter;
import org.apache.commons.io.filefilter.SuffixFileFilter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Collection;

public class Win1251ToUtf8 {

	private static final Logger logger = LoggerFactory.getLogger(Win1251ToUtf8.class);

	private static final String[] noConvertExtensions = {
		 ".zip", ".rar", ".doc", ".jar"
	};

	private static final String[] excludeFileNames = {
		 "converter_log.log", "converted"
	};

	public static void main(String[] args) throws IOException {
		logger.info("Starting converter");
		String workingDir;
		if (ArrayUtils.getLength(args) > 0) {
			workingDir = args[0];
		} else
			workingDir = System.getProperty("user.dir");
		try {
			convertationRun(workingDir);
		} catch (Exception e) {
			logger.error("Failed", e);
			System.exit(1);
		}
		logger.info("Finished");
	}

	public static void convertationRun(String root) {
		File currentDir = new File(root);
		logger.trace("Result directory is {}", currentDir);
		Collection<File> filesToConvert = FileUtils.listFiles(currentDir,
		                                                   new AndFileFilter(
			                                                    new NotFileFilter(new SuffixFileFilter(noConvertExtensions)),
			                                                    new NotFileFilter(new NameFileFilter(excludeFileNames))),
		                                                   new NotFileFilter(new NameFileFilter(excludeFileNames)));
		logger.info("{} files found", filesToConvert.size());

		File convertedDir = new File(currentDir, "converted");
		logger.trace("Result directory root is {}", convertedDir);
		if (!convertedDir.exists() && !convertedDir.mkdir()) throw new RuntimeException("Can not create directory " + convertedDir.getAbsolutePath());
		for (File srcFile : filesToConvert) {
			InputStreamReader inReader = null;
			OutputStreamWriter outWriter = null;
			try {
				logger.trace("Processing source file {}", srcFile);
				String relativePath = getRelativePath(currentDir, srcFile);
				logger.trace("Relative path is {}", relativePath);
				File targetFile = new File(convertedDir, relativePath);
				logger.trace("Target file location is {}", targetFile);
				FileUtils.forceMkdir(new File(targetFile.getParent()));
				inReader = new InputStreamReader(new FileInputStream(srcFile), "windows-1251");
				outWriter = new OutputStreamWriter(new FileOutputStream(targetFile), "UTF-8");
				IOUtils.copy(inReader, outWriter);
				logger.debug("File {} converted to {} ", srcFile, targetFile);
			} catch (Exception e) {
				logger.error("Processing of " + srcFile + " error", e);
			} finally {
				IOUtils.closeQuietly(inReader);
				IOUtils.closeQuietly(outWriter);
			}
		}
	}

	public static String getRelativePath(File baseDir, File target) {
		if (!baseDir.isDirectory())
			throw new IllegalArgumentException("Base dir " + baseDir + " is not a directory");
		if (!StringUtils.startsWith(target.getAbsolutePath(), baseDir.getAbsolutePath())) {
			throw new IllegalArgumentException("File " + target + " is not child of " + baseDir);
		}
		return StringUtils.substringAfter(target.getAbsolutePath(), baseDir.getAbsolutePath());
	}

}
